/*
  * Mirante Tecnologia
  * Copyright 2010, Mirante Informatica LTDA, 
  * and individual contributors as indicated by the @authors tag
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as
  * published by the Free Software Foundation; either version 2.1 of
  * the License, or (at your option) any later version.
  *
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this software; if not, write to the Free
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
package com.miranteinfo.seam.hibernate.validator;

import java.util.Arrays;
import java.util.List;

import org.hibernate.validator.Validator;

import com.miranteinfo.seam.hibernate.annotation.Cpf;

/**
 * Validador de CPF. 
 * 
 * @author lucas lins
 *
 */
public class CpfValidator implements Validator<Cpf> {
	
	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// ATTRIBUTES
	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	
	private boolean nullable;
	
	private List<String> cpfInvalidos = Arrays.asList(new String []{"00000000000","11111111111","22222222222","33333333333","44444444444","55555555555","66666666666","77777777777","88888888888","99999999999"});

	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// PUBLIC METHODS
	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	
	public void initialize(Cpf cpf) {
		this.nullable = cpf.nullable();
	}
	
	public boolean isValid(Object value) {
		
		if(!nullable && value == null) return false;

		if(nullable && value == null) return true;
		
		if (value != null && !isValidCPF(value.toString())) {
			return false;
		}else{
			return true;
		}
	}

	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// PRIVATE METHODS
	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	
	private boolean isValidCPF(String cpf) {
		
		if(cpfInvalidos.contains(cpf)) return false;
		
		if (cpf.trim().length() != 11) return false;

		String cpf1 = cpf.substring(0, 9); // rcpf1
		String cpf2 = cpf.substring(9); // rcpf2
		int i;

		int d1 = 0;
		for (i = 0; i < 9; i++) {
			d1 += Integer.parseInt(cpf1.substring(i, i + 1)) * (10 - i);
		}

		d1 = 11 - (d1 % 11);
		if (d1 > 9) {
			d1 = 0;
		}

		if (Integer.parseInt(cpf2.substring(0, 1)) != d1) {
			return false;
		}

		d1 *= 2;
		for (i = 0; i < 9; i++) {
			d1 += Integer.parseInt(cpf1.substring(i, i + 1)) * (11 - i);
		}

		d1 = 11 - (d1 % 11);
		if (d1 > 9) {
			d1 = 0;
		}

		if (Integer.parseInt(cpf2.substring(1, 2)) != d1) {
			return false;
		}

		return true;
	}

	
}
